// Copyright 2011, Vanya Davidenko.
// Используемая кодировка: UTF-8.

#ifndef LIBV_FILE_LINUX_REQUEST_COMPLETION_HANDLE_IMPL_HPP_
#define LIBV_FILE_LINUX_REQUEST_COMPLETION_HANDLE_IMPL_HPP_

#ifndef __linux__
# error "This header should be used in Linux only."
#endif

#include <aio.h>
#include <libv/atomic.h>
#include <libv/cast.h>
#include <libv/stdint.h>
#include <libv/acfile.h>



namespace libv
{

FileSlice ACFile::RequestCompletionHandle::RequestHandle2FileSilce(
    const RequestHandle& request_handle,
    const uint32_t num_bytes_to_transfer) const
{
    return FileSlice(request_handle.aio_nbytes, num_bytes_to_transfer);
}



enum ACFile::RequestCompletionHandle::Status
    ACFile::RequestCompletionHandle::StatusImpl() const
{
    const int r = ::aio_error(request_handle_);
    last_error_ = r;  // в errno ошибка от вызова aio_error, это не то

    const ssize_t expected_result =
        libv::IntegerCast<ssize_t>(request_handle_->aio_nbytes);

    if ( !r && ::aio_return(request_handle_) == expected_result )
        return COMPLETED;

    else if ( r == EINPROGRESS )
        return PENDING;

    else if ( r == ECANCELED )
        return CANCELED;
    else
        return FAILED;
}



bool ACFile::RequestCompletionHandle::WaitUntilFinishedImpl() const
{
    const bool result = ( ::aio_suspend(&request_handle_, 1, NULL) == 0 );
    last_error_ = errno;
    return result;
}



void ACFile::RequestCompletionHandle::DestructImpl()
{
}

}  // libv

#endif  // LIBV_FILE_LINUX_REQUEST_COMPLETION_HANDLE_IMPL_HPP_
